home *** CD-ROM | disk | FTP | other *** search
- /*
- * score.c - routines for drawing a PICT-based music score on the screen.
- */
-
- #include <quickdraw.h>
- #include <memory.h>
- #include <window.h>
- #include <resource.h>
- #include <control.h>
- #define ALLDIM 255 /* should be in control.h, but isn't */
- #include <event.h>
- #include <desk.h>
- #include <font.h>
-
- #include "ival.h"
-
- /*
- * SCORESPACES - total number of spaces per score:
- * 4 for each staff (treble and bass);
- * 2 between the staves;
- * 2 above the treble + 2 below the bass;
- * 1 above and 1 below for margins.
- */
-
- #define SCORESPACES 16 /* total number of spaces per score */
-
- /*
- * nobuts[] - buttons for the "Notation" window pane
- */
-
- #define NOSTRS 137 /* STR# */
- #define NO_GIVE 0 /* "Give Notation" */
- #define NO_COUNT 1
- static ControlHandle nobuts[NO_COUNT];
-
- /*
- * odegofdeg() - get the scale degree of an absolute degree.
- * Given a degree on the staff, return the degree within the octave.
- * NOTE: since staff degrees are relative to low C,
- * scale degrees go from C up to B rather than A to G.
- */
-
- #define odegofdeg(d) (d % DEGPEROCT)
-
- /*
- * treb/bass-flats/sharps[] - arrays of accidentals in the key signature.
- * Given in the order of # of flats/sharps in the key, each element gives
- * the degree (relative to low C) of that flat or sharp in the key
- * signature.
- */
-
- short trebflats[DEGPEROCT] = {
- 20, /* Bb */
- 23, /* Eb */
- 19, /* Ab */
- 22, /* Db */
- 18, /* Gb */
- 21, /* Cb */
- 17 /* Fb */
- };
- short bassflats[DEGPEROCT] = {
- 6, /* Bb */
- 9, /* Eb */
- 5, /* Ab */
- 8, /* Db */
- 4, /* Gb */
- 7, /* Cb */
- 3 /* Fb */
- };
- short trebsharps[DEGPEROCT] = {
- 24, /* F# */
- 21, /* C# */
- 25, /* G# */
- 22, /* D# */
- 19, /* A# */
- 23, /* E# */
- 20 /* B# */
- };
- short basssharps[DEGPEROCT] = {
- 10, /* F# */
- 7, /* C# */
- 11, /* G# */
- 8, /* D# */
- 5, /* A# */
- 9, /* E# */
- 6 /* B# */
- };
-
- /*
- * (local to iniacctab(), addacc() and accoftone().)
- *
- * acctab[] - array of accidentals implied in this measure so far.
- * Acctab[] records, for each scale degree, the current implied
- * accidental (if any) associated with that degree.
- * Indexed by the result of odegofdeg(), each acctab entry contains
- * a CH_* value.
- */
-
- short acctab[DEGPEROCT];
-
- /*
- * (local to notemouse() and unnote())
- *
- * mousetone - the (very temporary) note tracking the mouse.
- * mtonedrawn - "The mouse tone has been drawn onto the screen."
- * mousebits - a copy of what the screen looked like before the mousetone
- * was drawn. NOTE: mousebits is valid only if mtonedrawn is TRUE.
- */
-
- struct atone mousetone;
- int mtonedrawn = FALSE;
- BitMap mousebits;
-
- /*
- * chromedrag - TRUE if the mouse is dragging the chromatic adjustment
- * rather than the degree of a note.
- */
-
- int chromedrag;
-
- /*
- * *rect - Rect's enclosing the areas of the score.
- * Each of these rects should cover a vertical band of the score.
- */
-
- static Rect clefrect; /* clefs are left-justified into this rect */
- static Rect keyrect; /* the key accidentals are left-just'ed */
- static Rect tonerect[NUMTONES]; /* accidental is left, note is next */
- static short vmidc; /* vertical coord of middle C */
-
- /*
- * spaceheight - the (pixels) height of one space on the score
- * I.E., the distance from one line down to (but not including) the next.
- */
-
- static short spaceheight;
-
- #define MAXPICTS 4 /* max number of objects in a group + 1 */
-
- struct pictinfo {
- short resid[MAXPICTS]; /* resID's of the picts (0 == list end) */
- BitMap *bits[MAXPICTS]; /* pointers to the bitmaps */
- short width; /* pixels width of the widest pict */
- short vref; /* vertical distance from top to "zero" */
- };
-
- /*
- * CLEF*, clefpict - Clef (Bass and Treble) picture information.
- */
-
- #define CLEFTREB 0 /* clefpict[] index of Treble clef */
- #define CLEFBASS 1 /* ditto for Bass clef */
- #define CLEFNUM 2 /* number of clefpict[] entries */
- static struct pictinfo clefpict = {
- { 129, 130, 0} /* resID's of clefs */
- };
-
- /*
- * ACC*, accpict - Accidentals' (flat, natural, sharp) pict info.
- */
-
- #define ACCADJ (-CH_FLAT) /* conversion from CH_* to accpict[] */
- #define ACCNONE (-1) /* accpict[] idx code for no ACC*/
- #define ACCFLAT (ACCADJ + CH_FLAT) /* accpict[] idx of flat */
- #define ACCNAT (ACCADJ + CH_NAT) /* " " a natural */
- #define ACCSHARP (ACCADJ + CH_SHARP) /* " " a sharp */
- #define ACCNUM 3 /* number of accpict[] entries */
- static struct pictinfo accpict = {
- { 131, 132, 133, 0} /* resID's of accidentals */
- };
-
- /*
- * updurpict, dndurpict - Note durations' (whole note only) pict info.
- * Each note duration is represented once in each pict:
- * once pointing stem-up; once, stem-down.
- */
-
- #define DURWHOLE 0 /* *durpict[] index of a whole note */
- #define DURNUM 1 /* number of *durpict[] entries */
- static struct pictinfo updurpict = {
- { 134, 0} /* resID's of stem up versions of notes */
- };
- static struct pictinfo dndurpict = {
- { 135, 0} /* resID's of stem-down versions */
- };
-
- /*
- * getscore() - initialize the score element PICT info structures.
- */
-
- getscore()
- {
- short oldfont; /* original font of this port */
- Point delta; /* amount to offset each rect */
- short numstrs; /* number of strings in the button labels */
- short width; /* a width (in pixels) */
- Rect tmprect; /* a temporary variable */
- short i;
-
- /*
- * Get the pictures and their widths,
- * Then find the line spacing and the vertical references.
- * (See the MacPaint picture prototypes to understand the
- * values for vertical references.)
- */
-
- paw(&clefpict);
- paw(&accpict);
- paw(&updurpict);
- paw(&dndurpict);
-
- for (i = 0; i < CLEFNUM; ++i) {
- cvrandspace(clefpict.bits[i], &clefpict.vref);
- }
-
- /*
- * NOTE: vref's measure from the top-down, so they round
- * spaceheight / 2 down rather than rounding up.
- */
-
- accpict.vref = spaceheight + spaceheight / 2;
- updurpict.vref = 3 * spaceheight + spaceheight / 2;
- dndurpict.vref = spaceheight + spaceheight / 2;
-
- /*
- * find the score rectangle,
- * then split that rectangle into the necessary vertical bands.
- */
-
- scorerect.top = 0;
- scorerect.left = 0;
- scorerect.bottom = scorerect.top + SCORESPACES * spaceheight;
- vmidc = scorerect.top + SCORESPACES / 2 * spaceheight;
-
- clefrect.top = scorerect.top;
- clefrect.bottom = scorerect.bottom;
- clefrect.left = scorerect.left;
- clefrect.right = clefrect.left + clefpict.width;
-
- keyrect.top = scorerect.top;
- keyrect.bottom = scorerect.bottom;
- keyrect.left = clefrect.right;
- keyrect.right = keyrect.left + DEGPEROCT * accpict.width;
-
- tonerect[0].top = scorerect.top - 5; /* "5" is a hack for accidentals */
- tonerect[0].bottom = scorerect.bottom + 5;
- tonerect[0].left = keyrect.right + updurpict.width;
- tonerect[0].right = tonerect[0].left + accpict.width + updurpict.width
- + updurpict.width / 4;
-
- for (i = 1; i < NUMTONES; ++i) {
- tonerect[i].top = tonerect[i - 1].top;
- tonerect[i].bottom = tonerect[i - 1].bottom;
- tonerect[i].left = tonerect[i - 1].right + updurpict.width / 4;
- tonerect[i].right = tonerect[i].left +
- accpict.width + updurpict.width + updurpict.width / 4;
- }
-
- /*
- * Now that the Rects are placed relative to zero,
- * move the score structures so that they are centered within the pane.
- */
-
- scorerect.right = tonerect[NUMTONES - 1].right + updurpict.width / 4;
- delta.h = (noterect.left + noterect.right) / 2 -
- (scorerect.left + scorerect.right) / 2;
- delta.v = (noterect.top + noterect.bottom - BUTHEIGHT) / 2 -
- (scorerect.top + scorerect.bottom) / 2;
-
- OffsetRect(&scorerect, delta.h, delta.v);
- vmidc = scorerect.top + SCORESPACES / 2 * spaceheight;
-
- OffsetRect(&clefrect, delta.h, delta.v);
- OffsetRect(&keyrect, delta.h, delta.v);
- for (i = 0; i < NUMTONES; ++i) {
- OffsetRect(&tonerect[i], delta.h, delta.v);
- }
-
- /*
- * put this pane's control buttons against the left side of the pane.
- */
-
- oldfont = thePort->txFont;
- TextFont(BUTTONFONT);
- width = strswidth(NOSTRS, &numstrs) + BUTEXTRAH;
- tmprect.left = noterect.left + BUTHMARG;
- tmprect.right = tmprect.left + width;
- tmprect.bottom = noterect.bottom;
- tmprect.top = tmprect.bottom - BUTHEIGHT;
- delta.h = width + BUTHMARG;
- delta.v = 0;
- makeradcol(nobuts, BUTPROCID, NOSTRS, &tmprect, delta.h, delta.v);
-
- TextFont(oldfont);
- }
-
- /*
- * newtones() - reset the score controls, based on the new test state.
- */
-
- newtones()
- {
- /*
- * Hilite or Dim the "Give" control based on whether we give the 2nd tone
- */
-
- if (!progtasks.notate) {
- HiliteControl(nobuts[NO_GIVE], 0);
- tone1shown = FALSE;
- } else {
- HiliteControl(nobuts[NO_GIVE], ALLDIM);
- tone1shown = TRUE;
- }
- }
-
- /*
- * pickkey() - choose a random new value for the current key, curkey.
- */
-
- pickkey()
- {
- short i;
-
- curkey.insharps = randint(2); /* 0 = FALSE, 1 = TRUE */
- curkey.number = randint(DEGPEROCT + 1);
-
- InvalRect(&keyrect);
- for (i = 0; i < NUMTONES; ++i) {
- InvalRect(&tonerect[i]); /* (accidentals may have changed)*/
- }
- }
-
- /*
- * picktone() - choose a random pitch for the given tone.
- */
-
- picktone(tidx)
- short tidx; /* index of the tone to pick */
- {
- curtone[tidx].degree = randint(DEGPERSCORE);
- curtone[tidx].chrome = randint(NUM_CH) + CH_FLAT;
- InvalRect(&tonerect[tidx]);
- }
-
- /*
- * notepress() - handle a button-press in the Note pane.
- */
-
- notepress(whichcontrol)
- ControlHandle whichcontrol;
- {
- /* it must be "give" */
-
- sawtone1();
-
- }
-
- /*
- * sawtone1() - note that the second tone has been seen.
- */
-
- sawtone1()
- {
- HiliteControl(nobuts[NO_GIVE], ALLDIM);
- tone1shown = TRUE;
- InvalRect(&scorerect);
- }
-
- /*
- * drawscore() - draw the score within its window.
- * Assumes: thePort == windoc.
- */
-
- drawscore()
- {
- short n;
- Rect tmprect;
-
- drawstaff(vmidc - 5 * spaceheight);
- drawstaff(vmidc + spaceheight);
- drawbits(clefpict.bits[CLEFTREB], clefrect.left,
- vmidc - 5 * spaceheight - clefpict.vref);
- drawbits(clefpict.bits[CLEFBASS], clefrect.left,
- vmidc + spaceheight - clefpict.vref);
- drawkey(&curkey);
- iniacctab();
- for (n = 0; n < NUMTONES; ++n) {
- if (n != 1 || tone1shown) {
- drawtone(n, &curtone[n]);
- addacc(&curtone[n]);
- }
- }
- }
-
- /*
- * drawstaff() - draw a scorerect-wide staff at the given vertical.
- */
-
- drawstaff(topv)
- short topv; /* vertical coord of the top of the staff */
- {
- short v;
-
- MoveTo(scorerect.left, topv);
- LineTo(scorerect.left, topv + 4 * spaceheight);
-
- for (v = topv; v <= topv + 4 * spaceheight; v += spaceheight) {
- MoveTo(scorerect.left, v);
- LineTo(scorerect.right - 1, v);
- }
- }
-
- /*
- * drawkey() - draw the given key in the keyrect.
- */
-
- drawkey(kp)
- struct akey *kp; /* the key to draw */
- {
- short *list; /* current list of flats/sharps */
- BitMap *bmp; /* the sharp/flat bitmap */
- short i;
- short h; /* horz coord of the current flat/sharp */
-
- if (kp->insharps) {
- list = &trebsharps[0];
- bmp = accpict.bits[ACCSHARP];
- } else {
- list = &trebflats[0];
- bmp = accpict.bits[ACCFLAT];
- }
- for (i = 0, h = keyrect.left; i < kp->number;
- ++i, h += accpict.width) {
- drawbits(bmp, h, degtov(list[i]) - accpict.vref);
- }
-
- if (kp->insharps) {
- list = &basssharps[0];
- } else {
- list = &bassflats[0];
- }
- for (i = 0, h = keyrect.left; i < kp->number;
- ++i, h += accpict.width) {
- drawbits(bmp, h, degtov(list[i]) - accpict.vref);
- }
- }
-
- drawtone(tidx, tp)
- short tidx; /* index of the tone to draw */
- struct atone *tp; /* the tone to draw */
- {
- short degv; /* vertical of this degree */
- short acc; /* the accidental index (if any) */
- short degl; /* degree of this ledger-line */
-
- degv = degtov(tp->degree);
- acc = accoftone(tp);
-
- if (acc != ACCNONE) {
- drawbits(accpict.bits[acc], tonerect[tidx].left,
- degv - accpict.vref);
- }
- drawbits(dndurpict.bits[DURWHOLE],
- tonerect[tidx].left + accpict.width, degv - dndurpict.vref);
-
- /*
- * draw the necessary ledger-lines
- */
-
- if (tp->degree < DEG_LOWF) {
- for (degl = DEG_LOWF - 1; degl >= tp->degree; degl -= 2) {
- drawledger(tidx, degl);
- }
- } else if (tp->degree == DEG_MIDC) {
- drawledger(tidx, tp->degree);
- } else if (tp->degree > DEG_HIGG) {
- for (degl = DEG_HIGG + 1; degl <= tp->degree; degl += 2) {
- drawledger(tidx, degl);
- }
- }
- }
-
- /*
- * drawledger() - draw a ledger-line at the given degree
- * and within the given tone's rectangle.
- */
-
- drawledger(tidx, ldeg)
- short tidx; /* index of the tone this line is drawn for */
- short ldeg; /* degree to draw the line at */
- {
- short margin;
-
- margin = updurpict.width / 4;
- MoveTo(tonerect[tidx].left + accpict.width - margin, degtov(ldeg));
- Line(margin + updurpict.width + margin - 1, 0);
- }
-
- /*
- * notemouse() - update the placement of a note, based on the mouse position
- * (usually called between events).
- */
-
- notemouse(ptp)
- Point *ptp; /* where the mouse is (in some local coords) */
- {
- GrafPtr saveport;
- Point where; /* windoc coords of the mouse position */
- struct atone newtone; /* mouse coords interpreted as a tone */
- int newdrawn; /* "the new tone should be drawn" */
- short vtodeg();
- short dvtochrome();
-
- /*
- * Select our window, converting the mouse point as we do it.
- */
-
- GetPort(&saveport);
- where = *ptp;
- LocalToGlobal(&where);
- SetPort(windoc);
- GlobalToLocal(&where);
-
- /*
- * We draw a tone only if:
- * The second hasn't already been given;
- * our window is selected;
- * the mouse is inside the score.
- */
-
- newdrawn = !tone1shown && (saveport == windoc)
- && PtInRect(pass(where), &scorerect);
-
- if (newdrawn) {
- if (chromedrag) {
-
- /*
- * dragging the chromatic adjustment,
- * we assume the mousetone.degree has already been set
- * by a recent call to notemouse().
- */
-
- newtone.degree = mousetone.degree;
- newtone.chrome = dvtochrome(newtone.degree, where.v);
- } else {
- newtone.degree = vtodeg(where.v);
- newtone.chrome = chromeofdeg(newtone.degree);
- }
- }
-
- /*
- * If things haven't changed, we're done.
- */
-
- if (newdrawn == mtonedrawn && (!mtonedrawn ||
- (mousetone.degree == newtone.degree &&
- mousetone.chrome == newtone.chrome))) {
- SetPort(saveport);
- return;
- }
-
- /*
- * If there was a previous mouse tone,
- * remove it by copying the blank score onto it.
- */
-
- if (mtonedrawn) {
- CopyBits(&mousebits, &(thePort->portBits),
- &(mousebits.bounds), &tonerect[1], srcCopy, (RgnHandle) 0);
- }
-
- /*
- * If we are to draw a new tone, do it:
- * Save the underlying bits (this step initializes mousebits);
- * Draw the new tone.
- */
-
-
- mtonedrawn = newdrawn;
- if (mtonedrawn) {
- mousetone = newtone;
- }
- if (mtonedrawn) {
- if (!mousebits.baseAddr) {
- topLeft(mousebits.bounds) = topLeft(tonerect[1]);
- botRight(mousebits.bounds) = botRight(tonerect[1]);
- mousebits.rowBytes =
- (mousebits.bounds.right - mousebits.bounds.left + 7) / 8;
- if (mousebits.rowBytes & 1) ++mousebits.rowBytes;
- mousebits.baseAddr = (QDPtr) NewPtr((Ptr) (mousebits.rowBytes *
- (mousebits.bounds.bottom - mousebits.bounds.top)));
- }
- CopyBits(&(thePort->portBits), &mousebits, &tonerect[1], &mousebits.bounds,
- srcCopy, (RgnHandle) 0);
- drawtone(1, &mousetone);
- }
-
- SetPort(saveport);
- }
-
- /*
- * drawmouse() - draw the current state of the mouse note.
- * This routine is called only when redrawing the whole window.
- * NOTE: this routine assumes the port is set to windoc.
- */
-
- drawmouse()
- {
- if (mtonedrawn) {
- CopyBits(&mousebits, &(thePort->portBits), &(mousebits.bounds), &tonerect[1],
- srcCopy, (RgnHandle) 0);
- drawtone(1, &mousetone);
- }
- }
-
- /*
- * unnote() - remove the current note drawn by notemouse().
- */
-
- unnote()
- {
- GrafPtr saveport;
-
- if (!mtonedrawn) return;
- GetPort(&saveport);
- SetPort(windoc);
-
- CopyBits(&mousebits, &(thePort->portBits), &(mousebits.bounds), &tonerect[1],
- srcCopy, (RgnHandle) 0);
-
- mtonedrawn = FALSE;
- SetPort(saveport);
- }
-
- /*
- * dropnote() - place a note where the mouse was pressed
- */
-
- dropnote(ptp)
- Point *ptp; /* mouse-down point */
- {
- struct atone mtone; /* the tone associated with the mouse */
-
- if (tone1shown || !PtInRect(pass(*ptp), &scorerect)) return;
-
- mtone.degree = vtodeg(ptp->v);
- mtone.chrome = chromeofdeg(mtone.degree);
-
- notemouse(ptp);
- chromedrag = TRUE;
- while (StillDown()) {
- SystemTask();
- GetMouse(ptp);
- notemouse(ptp);
- }
- mtone.chrome = dvtochrome(mtone.degree, ptp->v);
- chromedrag = FALSE;
- unnote();
-
- /*
- * If the mouse was released outside the score, treat it as a 'cancel'.
- * Otherwise, If the user got the note right, mark it.
- */
-
- if (!PtInRect(pass(*ptp), &scorerect)) {
- return;
- }
- if (mtone.degree == curtone[1].degree && mtone.chrome == curtone[1].chrome) {
- sawtone1();
- }
- }
-
- /*
- * accoftone() - given a tone, return the accidental to draw for that
- * tone, based on what tones have been registered via addacc() since the last
- * iniacctab() call.
- */
-
- int /* ACC* of the tone */
- accoftone(tp)
- struct atone *tp; /* the tone to analyze */
- {
- short odeg; /* the tone's degree within an octave */
- short chrome; /* the assumed chromatic of this degree */
-
- odeg = odegofdeg(tp->degree);
- if (tp->chrome == acctab[odeg]) {
- return(ACCNONE);
- }
- return(ACCADJ + tp->chrome);
- }
-
- /*
- * iniacctab() - reset the accidental table, based on the current key.
- */
-
- iniacctab()
- {
- short *list; /* current list of flats/sharps */
- short odeg; /* degree within an octave */
- short i;
- short chrome; /* chromatic modification to use */
-
- for (odeg = 0; odeg < DEGPEROCT; ++odeg) {
- acctab[odeg] = chromeofdeg(odeg);
- }
- }
-
- /*
- * addacc() - given a tone, add it's chromatic change to the current
- * set of accidentals.
- */
-
- addacc(tp)
- struct atone *tp;
- {
- short odeg; /* the tone's degree within an octave */
- short chrome; /* the assumed chromatic of this degree */
-
- odeg = odegofdeg(tp->degree);
- acctab[odeg] = tp->chrome;
- }
-
- /*
- * chromeofdeg() - given any degree,
- * chromeofdeg() returns the chromatic adjustment of that note
- * based only on the current key signature.
- */
-
- int
- chromeofdeg(deg)
- short deg; /* any degree on the score */
- {
- short *list; /* current list of flats/sharps */
- short i;
- short chrome; /* chromatic modification of the key */
- int ret; /* chromatic modification to return */
-
- ret = CH_NAT;
-
- if (curkey.insharps) {
- list = &trebsharps[0];
- chrome = CH_SHARP;
- } else {
- list = &trebflats[0];
- chrome = CH_FLAT;
- }
- for (i = 0; i < curkey.number; ++i) {
- if (odegofdeg(deg) == odegofdeg(list[i])) {
- ret = chrome;
- }
- }
- return(ret);
- }
-
- /*
- * drawbits() - OR the given bitmap into the given point of the window.
- */
-
- drawbits(bmp, left, top)
- BitMap *bmp; /* the bitmap to draw */
- short left, top; /* the top-left of where to put that bitmap */
- {
- Rect dstrect;
-
- topLeft(dstrect) = topLeft(bmp->bounds);
- botRight(dstrect) = botRight(bmp->bounds);
- OffsetRect(&dstrect, -dstrect.left + left, -dstrect.top + top);
- CopyBits(bmp, &(thePort->portBits), &(bmp->bounds), &dstrect,
- srcOr, (RgnHandle) 0);
- }
-
- /*
- * degtov() - convert from a degree number to the corresponding
- * vertical coordinate.
- */
-
- short
- degtov(degree)
- {
- return(scorerect.bottom - spaceheight -
- (degree * spaceheight + 1) / 2);
- }
-
- /*
- * vtodeg() - convert from a vertical coord to a degree.
- */
-
- short
- vtodeg(v)
- short v;
- {
- short dv; /* distance from the point to the '0' degree */
- short deg; /* the degree to return */
-
- dv = scorerect.bottom - spaceheight - v;
- deg = (dv * 2 + (spaceheight + 1) / 2) / spaceheight;
-
- if (deg < 0) {
- deg = 0;
- } else if (deg >= DEGPERSCORE) {
- deg = DEGPERSCORE - 1;
- }
- return(deg);
- }
-
- /*
- * dvtochrome() - given a degree and a new vertical,
- * return the chromatic change for that degree.
- * Used to let the mouse control the chromatic change in a note.
- */
-
- short
- dvtochrome(deg, v)
- short deg;
- short v;
- {
- short chrome;
- int delta;
-
- /*
- * Adjust the chromatic change only if accidentals are allowed.
- */
-
- chrome = chromeofdeg(deg);
- if (acc_ok) {
- delta = ((scorerect.bottom - spaceheight - v) * 2 + (spaceheight + 1) / 2)
- / spaceheight - deg;
- chrome += delta;
- }
- if (chrome < CH_FLAT) {
- chrome = CH_FLAT;
- } else if (chrome > CH_SHARP) {
- chrome = CH_SHARP;
- }
- return(chrome);
- }
-
- /*
- * paw() - get an array of pict bitmaps and their maximum width.
- * I.E., given a pictinfo struct that has the resid[] array set,
- * fill in its picts[] array and its 'width' field.
- */
-
- paw(infop)
- struct pictinfo *infop;
- {
- short i;
- PicHandle pih; /* handle to this pict */
- short width; /* width of this pict */
- BitMap *PictToMap();
-
- infop->width = 0;
- for (i = 0; infop->resid[i]; ++i) {
- pih = (PicHandle) GetResource((long) 'PICT', infop->resid[i]);
- infop->bits[i] = PictToMap(pih);
-
- width = infop->bits[i]->bounds.right - infop->bits[i]->bounds.left;
- if (infop->width < width) {
- infop->width = width;
- }
- }
- }
-
- /*
- * cvrandspace() - Given a clef Bitmap,
- * find the clef's offset (vref) and the score's line spacing (spaceheight).
- *
- * Do it by examining that bitmap to find where the lines are.
- */
-
- cvrandspace(bmp, vrp)
- BitMap *bmp; /* pointer to the clef's bitmap */
- short *vrp; /* where to put the clef's vref */
- {
- GrafPtr saveport;
- BitMap savebits; /* current port's original bitmap */
- short v; /* current vertical pixel being examined*/
-
- GetPort(&saveport);
- SetPort(windoc);
- savebits.baseAddr = thePort->portBits.baseAddr;
- savebits.rowBytes = thePort->portBits.rowBytes;
- topLeft(savebits.bounds) = topLeft(thePort->portBits.bounds);
- botRight(savebits.bounds) = botRight(thePort->portBits.bounds);
- SetPortBits(bmp);
-
- v = -1;
- while (!GetPixel(0, ++v)) /* find the top of the first line */
- ;
- *vrp = v;
-
- while (GetPixel(0, ++v)) /* skip past the bottom of that line */
- ;
-
- while (!GetPixel(0, ++v)) /* find the top of the next line */
- ;
-
- spaceheight = v - *vrp;
-
- SetPortBits(&savebits);
- SetPort(saveport);
- }
-